﻿using DataType;
using DataType.CustomEnumType;
using DataType.JudgeResults;
using DataType.MessageType;
using MapCalclator;
using OprsSimulator.Operators;
using OprsSimulator.OprAttributes;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Collections.Specialized.BitVector32;

namespace OprsSimulator
{
    public class OprsSimulator
    {
        private List<IOperator> operators = new List<IOperator>();

        public List<IOperator> Operators { get => operators; set => operators = value; }

        private List<IOperator> passengers = new List<IOperator>();
        public List<IOperator> Passengers { get => passengers; set => passengers = value; }

        private List<IOperator> dead_oprs = new List<IOperator>();
        public List<IOperator> DeadOprs { get => dead_oprs; set => dead_oprs = value; }

        #region
        //public void SetObserveDistance(IOperator opr)
        //{
        //    if (typeof(IReconnaissanceAttris).IsAssignableFrom(opr.GetType()) && (Dictionary<OprSubType, int>)opr.GetType().GetProperty("ObserveDistance").GetValue(opr) == null)
        //    {
        //        Dictionary<OprSubType, int> observeDistance = null;
        //        OprType oprType = (OprType)opr.GetType().GetProperty("Type").GetValue(opr);
        //        //车辆、步兵
        //        if (oprType == OprType.Vehicle || oprType == OprType.Infantry)
        //        {
        //            observeDistance = new Dictionary<OprSubType, int>
        //                {
        //                    {OprSubType.Tank, 25},
        //                    {OprSubType.IFV, 25},
        //                    {OprSubType.Infantry, 10},
        //                    {OprSubType.Artillery, 10},
        //                    {OprSubType.UGV, 25},
        //                    {OprSubType.Drone, 1},
        //                    {OprSubType.Helicopter, 25},
        //                    {OprSubType.CruisingMissile, 1},
        //                };
        //            opr.GetType().GetProperty("ObserveDistance").SetValue(opr, observeDistance);
        //        }
        //        //飞机
        //        if (oprType == OprType.Airplane)
        //        {

        //            OprSubType oprSubType = (OprSubType)opr.GetType().GetProperty("Subtype").GetValue(opr);
        //            //无人机、巡飞弹
        //            if (oprSubType == OprSubType.Drone || oprSubType == OprSubType.CruisingMissile)
        //            {
        //                observeDistance = new Dictionary<OprSubType, int>
        //                    {
        //                        {OprSubType.Tank, 2},
        //                        {OprSubType.IFV, 2},
        //                        {OprSubType.Infantry, 2},
        //                        {OprSubType.Artillery, 2},
        //                        {OprSubType.UGV, 2},
        //                        {OprSubType.Drone, 0},
        //                        {OprSubType.Helicopter, 0},
        //                        {OprSubType.CruisingMissile, 0},
        //                    };
        //            }
        //            //直升机
        //            if (oprSubType == OprSubType.Helicopter)
        //            {
        //                observeDistance = new Dictionary<OprSubType, int>
        //                    {
        //                        {OprSubType.Tank, 25},
        //                        {OprSubType.IFV, 25},
        //                        {OprSubType.Infantry, 10},
        //                        {OprSubType.Artillery, 10},
        //                        {OprSubType.UGV, 25},
        //                        {OprSubType.Drone, 1},
        //                        {OprSubType.Helicopter, 25},
        //                        {OprSubType.CruisingMissile, 1},
        //                    };
        //            }
        //            if (observeDistance == null) return;
        //            opr.GetType().GetProperty("ObserveDistance").SetValue(opr, observeDistance);
        //        }
        //    }
        //}
        //public void CompleteAttris()
        //{
        //    for (int i = 0; i < operators.Count; i++)
        //    {
        //        //ObserveDistance无值
        //        SetObserveDistance(operators[i]);
        //    }
        //    for (int i = 0; i < passengers.Count; i++)
        //    {
        //        SetObserveDistance(operators[i]);
        //    }
        //}
        #endregion
        /// <summary>
        /// 根据OnBoard属性，分配算子到operators或者passengers中
        /// </summary>
        public void AssignOperators()
        {
            List<IOperator> operator_oprs = new List<IOperator>();// 用于存储乘客里不在车上的算子
            List<IOperator> passenger_oprs = new List<IOperator>();// 用于存储算子里已经上车的乘客
            // 找出operators中在车上的算子
            for (int i = 0; i < operators.Count; i++)
            {
                if (!typeof(IMoveAttris).IsAssignableFrom(operators[i].GetType())) continue;// 没有继承IMoveAttris接口，没有OnBoard属性
                if ((bool)operators[i].GetType().GetProperty("OnBoard").GetValue(operators[i]))// 算子的OnBoard属性为true
                {
                    passenger_oprs.Add(operators[i]);// 添加进passenger_oprs
                }
            }
            // 找出passengers中不在车上的算子
            for (int i = 0; i < passengers.Count; i++)
            {
                if (!typeof(IMoveAttris).IsAssignableFrom(operators[i].GetType())) continue;// 没有继承IMoveAttris接口，没有OnBoard属性
                if (!(bool)passengers[i].GetType().GetProperty("OnBoard").GetValue(passengers[i]))// 乘客的OnBoard属性为false
                    operator_oprs.Add(passengers[i]);// 添加进operator_oprs
            }

            // 移除和添加
            foreach (IOperator operator_opr in operator_oprs)// 将 乘客里不在车上的算子 从乘客中删除，添加进算子中
            {
                passengers.Remove(operator_opr);
                operators.Add(operator_opr);
            }
            foreach (IOperator passenger_opr in passenger_oprs)// 将 算子里已经上车的乘客 从算子中删除，添加进乘客中
            {
                operators.Remove(passenger_opr);
                passengers.Add(passenger_opr);
            }
        }
        /// <summary>
        /// 根据裁决信息更新operators的独立属性，删除算子
        /// </summary>
        /// <param name="judgeResults"></param>
        public void UpdateStandalone(List<IJudgeResult> judgeResults, Map map)
        {
            List<IOperator> dead_oprs = new List<IOperator>();// 记录本次裁决中死亡的算子

            for (int i = 0; i < operators.Count; i++)// 遍历全部算子，更新算子属性信息
            {
                // 根据裁决结果更新属性
                operators[i].UpdataStandaloneAttris(judgeResults, map);

                // 删除血量为0的算子
                if (!typeof(ICommonAttris).IsAssignableFrom(operators[i].GetType())) continue;// 没有血量属性的算子，跳过
                if ((int)operators[i].GetType().GetProperty("Blood").GetValue(operators[i]) <= 0)// 如果血量为0
                {
                    dead_oprs.Add(operators[i]);// 添加进dead_oprs

                    // 如果可以搭载算子（即重型战车），删除其乘客和态势所属无人战车和巡飞弹
                    if (!typeof(ICarryingAttris).IsAssignableFrom(operators[i].GetType())) continue;
                    //死亡的算子搭载的算子也死亡
                    List<int> passenger_ids = (List<int>)operators[i].GetType().GetProperty("PassengerIDs").GetValue(operators[i]);// 取出乘客id
                    passenger_ids = passenger_ids ?? new List<int>();// 如果为空就new一个
                    if (passenger_ids.Count > 0)// 如果有搭载乘客
                    {
                        foreach (IOperator passenger in passengers)// 在passengers中找到此车辆算子搭载的乘客
                        {
                            if (passenger_ids.Contains(passenger.ObjID) && operators[i].ObjID == (int)passenger.GetType().GetProperty("Car").GetValue(passenger))
                            {
                                dead_oprs.Add(passenger);// 添加进dead_oprs
                            }
                        }
                    }

                    // 死亡的算子所属的无人战车和巡飞弹也死亡(目标为态势中的，在车上的和其他乘客算子一起统一删除)
                    List<int> launch_ids = (List<int>)operators[i].GetType().GetProperty("LaunchIDs").GetValue(operators[i]);// 获取车辆算子发射出去的算子id
                    launch_ids = launch_ids ?? new List<int>();// 如果为空就new一个
                    if (launch_ids.Count > 0)// 如果有发射的算子
                    {
                        foreach (IOperator op in operators)
                        {
                            if (launch_ids.Contains(op.ObjID))// 在operators中找到
                            {
                                OprSubType oprSubType = (OprSubType)op.GetType().GetProperty("Subtype").GetValue(op);// 取得算子的类型
                                // 如果是无人战车和巡飞弹
                                if (oprSubType == OprSubType.UGV || oprSubType == OprSubType.CruisingMissile)
                                {
                                    dead_oprs.Add(op);// 添加进dead_oprs
                                }
                            }
                        }
                    }
                }
            }
            // 删除
            if (this.dead_oprs == null) this.dead_oprs = new List<IOperator>();// 初始化类的dead_oprs属性
            else this.dead_oprs.Clear();
            if (dead_oprs.Count > 0)// 如果有会被删除的算子
            {
                foreach (IOperator dead_opr in dead_oprs)// 删除
                {
                    operators.Remove(dead_opr);
                    passengers.Remove(dead_opr);
                }
                this.dead_oprs.AddRange(dead_oprs);// 删除的算子暂存在dead_oprs字段中
            }
        }
        /// <summary>
        /// 根据车辆算子被攻击和被压制情况更新乘客算子，需要场上算子更新完成之后更新，即先调用UpdateStandalone方法再调用此方法（没有合并是考虑到后面分布式）
        /// </summary>
        /// <param name="judgeResults"></param>
        /// <param name="oprs"></param>
        /// <param name="map"></param>
        public void UpdatePassengers(List<IJudgeResult> judgeResults, List<IOperator> oprs, Map map)
        {
            List<IOperator> dead_oprs = new List<IOperator>();// 记录本次裁决中死亡的算子
            for (int i = 0; i < passengers.Count; i++)
            {
                //1.下车属性修改   2.车辆算子被射击时，车上步兵也会受到伤害
                passengers[i].UpdataStandaloneAttris(judgeResults, map);

                if (!typeof(ICommonAttris).IsAssignableFrom(passengers[i].GetType())) continue;// 没有血量属性
                // 车上步兵生命值为0
                if ((int)passengers[i].GetType().GetProperty("Blood").GetValue(passengers[i]) <= 0)
                {
                    dead_oprs.Add(passengers[i]);// 添加进dead_oprs
                }
            }
            // 删除
            if (dead_oprs.Count > 0)// 如果有死亡的乘客
            {
                foreach (IOperator dead_opr in dead_oprs)
                {
                    passengers.Remove(dead_opr);// 从乘客中移除
                }
                // this.dead_oprs每轮的初始化和清空在UpdateStandalone方法中
                this.dead_oprs.AddRange(dead_oprs);// 暂存到类的dead_oprs字段中
            }
        }

        /// <summary>
        /// 根据更新后的operators属性，更新交互属性
        /// </summary>
        /// <param name="oprs"></param>
        public void UpdateAssociated(List<IOperator> oprs, List<IOperator> passengers, Map map)
        {
            for (int i = 0; i < operators.Count; i++)// 更新算子
            {
                operators[i].UpdateAssociatedAttris(oprs, passengers, map);
            }
            for (int i = 0; i < this.passengers.Count; i++)// 更新乘客
            {
                this.passengers[i].UpdateAssociatedAttris(oprs, passengers, map);//检测车辆是否被压制
            }
        }

        public Dictionary<int, Dictionary<int, List<ActionMsg>>> ConfirmValidActions(List<OperatorMsg> oprs, CityMsg[] cities, Map map, ShootJudgeTable shootJudgeTable)
        {
            Dictionary<int, Dictionary<int, List<ActionMsg>>> valid_actions = new Dictionary<int, Dictionary<int, List<ActionMsg>>>();// 保存更新好的合法动作，用于返回
            for (int i = 0; i < operators.Count; i++)// 调用每个算子的更新方法
            {
                Dictionary<int, List<ActionMsg>> individualValidActions = operators[i].ConfirmValidActions(oprs, cities, map, shootJudgeTable, passengers);// 调用方法更新，并接收更新好的值

                if (valid_actions.ContainsKey(operators[i].ObjID))// 如果id已经存在
                {
                    valid_actions[operators[i].ObjID] = individualValidActions;// 重新赋值
                }
                else
                {
                    valid_actions.Add(operators[i].ObjID, individualValidActions);// 如果不存在就添加键和值
                }
            }

            return valid_actions;
        }
    }
}
